<?php

use Symfony\Component\VarExporter\VarExporter;
use think\facade\App;
use think\facade\Config;
use think\helper\Str;

/**
 * 获得插件目录
 */
function addons_path(string $name=''){
	return root_path('addons') . ($name?$name.DS:$name);
}

// 如果插件目录不存在则创建
if (!is_dir(addons_path())) {
	@mkdir(addons_path(), 0755, true);
}

// 插件类库自动载入
// spl_autoload_register(function($classname){
// 	$classname = ltrim($classname,'\\');
// 	$nspre = 'addons\\';
//     if (str_starts_with($classname,$nspre)) {
//         $file = addons_path().str_replace("\\",DS, substr($classname,strlen($nspre))).'.php';
//         if (file_exists($file)) {
//             require_once $file;
//             return true;
//         }
//         return false;
//     }
//     return false;
// });
addNamespace('addons\\',addons_path());

/**
 * 获得插件列表
 * @return array
 */
function get_addons_list()
{
    $dirs = scandir(addons_path());
    $r = [];
    foreach ($dirs as $name) {
        if ($name === '.' or $name === '..') continue;
        if (is_file(addons_path() . $name)) continue;
        $addonDir = addons_path() . $name . DS;
        if (!is_dir($addonDir)) continue;
        if (!is_file($addonDir . ucfirst($name) . '.php')) continue;

        $info_file = $addonDir . 'info.ini';
        if (!is_file($info_file)) continue;

        $info = parse_ini_file($info_file, true, INI_SCANNER_TYPED) ?: [];
        if (!isset($info['name'])||$info['name']!==$name) continue;
        // $info['url'] = addon_url($name);
        $r[$name] = $info;
    }
    return $r;
}

if (!function_exists('get_addon_class')) {
    /**
     * 获取插件类的类名
     * @param string $name 插件名称
     * @param string $class 当前类名
     * @param string $type 返回命名空间类型
     * @return string
     */
    function get_addon_class($name, $class = '', $type = '')
    {
        $name = trim($name);
        if ($class && strpos($class, '.')) {
            $class = explode('.', $class);
            $class[count($class) - 1] = Str::studly(end($class));
            $class = implode('\\', $class);
        } else {
            $class = Str::studly(!$class ? $name : $class);
        }
        switch ($type) {
            case 'controller':
                $full_class = '\\addons\\' . $name .  '\\controller\\' . $class;
                break;
            default:
                $full_class = '\\addons\\' . $name . '\\' .ucfirst($name);
        }
        return class_exists($full_class) ? $full_class : '';
    }
}

if (!function_exists('get_addon_instance')) {
    /**
     * 获取插件的单例
     * @param string $name 插件名称
     * @return mixed|null
     */
    function get_addon_instance($name)
    {
        static $_addons_ins = [];
        if (isset($_addons_ins[$name])) {
            return $_addons_ins[$name];
        }
        $class = get_addon_class($name);
        if (class_exists($class)) {
            return $_addons_ins[$name] = new $class(app());
        }
    }
}

if (!function_exists('get_addon_info')) {
    /**
     * 读取插件基础信息
     * @param string $name 插件名称
     * @return array
     */
    function get_addon_info($name)
    {
        if ($addon = get_addon_instance($name)) {
	        return $addon->getInfo();
        }
        return [];
    }
}

if (!function_exists('get_addon_config')) {
    /**
     * 获取插件的配置
     * @param string $name 插件名称
     * @return array
     */
    function get_addon_config($name)
    {
        if ($addon = get_addon_instance($name)) {
     	   return $addon->getConfig($name);
        }
        return [];
    }
}

if (!function_exists('set_addon_info')) {
	/**
	 * 设置插件基础信息
	 * @param string $name 插件名称
	 * @param array $array 配置数据
	 * @return bool
	 * @throws Exception
	 */
    function set_addon_info(string $name, array $array)
    {
        $file = addons_path($name) . 'info.ini';
        $addon = get_addon_instance($name);
        if (!$addon) {
        	throw new Exception("插件({$name})不存在");
        }
        $info = $addon->setInfo($name, $array);
	    if (!isset($info['name']) || !isset($info['title']) || !isset($info['version'])) {
	        throw new Exception("插件配置写入失败");
	    }
        $res = array();
        foreach ($info as $key => $val) {
            if (is_array($val)) {
                $res[] = "[$key]";
                foreach ($val as $k => $v)
                    $res[] = "$k = " . (is_numeric($v) ? $v : $v);
            } else
                $res[] = "$key = " . (is_numeric($val) ? $val : $val);
        }
        if (file_put_contents($file,implode("\n",$res)."\n",LOCK_EX)) {
            //清空当前配置缓存
            Config::set($info, "addoninfo_{$name}");
        }else{
        	throw new Exception("文件没有写入权限");
        }
        return true;
    }
}

if (!function_exists('set_addon_config')) {
	/**
	 * 写入配置文件
	 * @param string  $name      插件名
	 * @param array   $config    配置数据
	 * @param bool $writefile 是否写入配置文件
	 * @return bool
	 * @throws Exception
	 */
	function set_addon_config($name, $config, $writefile = true)
	{
	    $addon = get_addon_instance($name);
	    $addon->setConfig($name, $config);
	    $fullconfig = get_addon_fullconfig($name);
	    foreach ($fullconfig as $k => &$v) {
	        if (isset($config[$v['name']])) {
	            $value = $v['type'] !== 'array' && is_array($config[$v['name']]) ? implode(',', $config[$v['name']]) : $config[$v['name']];
	            $v['value'] = $value;
	        }
	    }
	    if ($writefile) {
	        // 写入配置文件
	        set_addon_fullconfig($name, $fullconfig);
	    }
	    return true;
	}
}

if (!function_exists('get_addon_fullconfig')) {
    /**
     * 读取配置文件
     *
     * @param string $name  插件名
     * @param array  $array 配置数据
     * @return boolean
     * @throws Exception
     */
    function get_addon_fullconfig($name)
    {
        $file = addons_path($name) . 'config.php';
        if (!file_exists($file)) {
            return [];
        }
        return include($file);
    }
}

if (!function_exists('set_addon_fullconfig')) {
	/**
	 * 写入配置文件
	 *
	 * @param string $name  插件名
	 * @param array  $array 配置数据
	 * @return boolean
	 * @throws Exception
	 */
	function set_addon_fullconfig($name, $array)
	{
	    $file = addons_path($name) . 'config.php';
	    $ret = file_put_contents($file, "<?php\n\n" . "return " . VarExporter::export($array) . ";\n", LOCK_EX);
	    if (!$ret) {
	        throw new Exception("配置写入失败");
	    }
	    return true;
	}
}
